#pragma once
#include <time.h>
#include <stdio.h>
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <sys/eventfd.h>
#include <signal.h>
#include <vector>
#include <string>
#include <functional>
#include <unordered_map>
#include <memory>
#include <list>
#include <thread>
#include <mutex>
#include <condition_variable>

/*----------------------简单日志宏的实现-------------------------*/
// 日志等级
#define NORMAL 0    // 正常
#define DEBUG  1    // 调试
#define ERROR  2    // 错误
#define LOG_LEVEL DEBUG// 控制输出

/*strftime:将struct tm结构体对象自动转换成字符串*/
#define LOG(level,format,...) do{\
    if(level < LOG_LEVEL) break;\
    time_t t = time(nullptr);\
    struct tm *ltm = localtime(&t);\
    char tmp[32] = {0};\
    strftime(tmp,sizeof(tmp) - 1,"%H:%M:%S",ltm);\
    fprintf(stdout,"[thread:%p]--[%s]--[file:%s|line:%d]=> " format "\n",(void *)pthread_self(),tmp,__FILE__,__LINE__,##__VA_ARGS__);\
}while(0)

#define NORMAL_LOG(format,...) LOG(NORMAL,format,##__VA_ARGS__)
#define DEBUG_LOG(format,...) LOG(DEBUG,format,##__VA_ARGS__)
#define ERROR_LOG(format,...) LOG(ERROR,format,##__VA_ARGS__)
/*----------------------简单日志宏的实现-------------------------*/


/*-----------------------Buffer模块：
功能：1.提供一个用户层的缓冲区，并提供一些数据存取的接口，方便用户使用
      2.提供数据缓存的功能，这对协议支持有利，比如接收到一个不完整的请求时，Buffer模块有能力将数据缓存起来----------------------------------*/
#define BUFFER_DEFAULT_SIZE 1024// Buffer模块的默认大小
class Buffer
{
public:
    Buffer()
        :_reader(0),_writer(0),_buffer(BUFFER_DEFAULT_SIZE)
    {}

    char *Begin() {return &(*(_buffer.begin()));}// 获取缓冲区的起始地址(整个Buffer的起始地址，并不是有效数据的起始地址)

    char *WritePosition() {return Begin() + _writer;}// 获取有效数据的结束位置(最后一个有效元素的下一个位置)，也就是新数据想要写入的起始位置

    char *ReadPosition() {return Begin() + _reader;}// 获取有效数据的起始位置，也就是要读取的数据的起始位置

    uint64_t TailFreeSize() {return _buffer.size() - _writer;}// 计算_writer之后的空闲空间大小

    uint64_t HeadFreeSize() {return _reader;}// 获取_reader之前的空间空间大小

    uint64_t ReadAbleSize() {return _writer - _reader;}// 获取可读数据大小(有效数据的大小)

    void OffsetReader(uint64_t len)// _reader向后移动，说明有数据被读走
    {
        if(len == 0) return;// 如果要读取的数据长度为0
        if(len > ReadAbleSize()) abort();// 最多和_writer处于同一位置，说明Buffer为空，超过_writer就是未定义的行为
        _reader += len;
    }

    void OffsetWriter(uint64_t len)// _writer向后移动，说明有新数据写入
    {
        if(len == 0) return;
        if(len > TailFreeSize()) abort();// 最多移动到当前_buffer的最大容量处，一旦超出就可能造成越界访问
        _writer += len;
    }

    void EnsureWriteSpace(uint64_t len)// 确保空间大小足够容纳新数据
    {
        if(TailFreeSize() >= len) return;// _writer尾部有足够的空间容纳新数据
        if(TailFreeSize() + HeadFreeSize() >= len)// _reader之前、_writer之后的空间足够容纳新数据
        {
            uint64_t oldsize = ReadAbleSize();// 保存当前有效数据大小
            std::copy(ReadPosition(),ReadPosition() + oldsize,Begin());// 将数据往前挪动
            _reader = 0;_writer = oldsize;
        }
        else // 当前Buffer没有足够的空间容纳新数据
        {
            //("Buffer Resize: %ld",_writer + len);
            _buffer.resize(_writer + len);// 扩容
        }
    }

    void Write(const void *data,uint64_t len)// 向Buffer写入数据
    {
        if(len == 0) return;
        EnsureWriteSpace(len);// 写入数据之前一定要确保有足够的空间
        const char *d = (const char *)data;
        std::copy(d,d + len,WritePosition());// 将[d,d+len]这段区间的数据拷贝到_writer指向的位置之后
    }

    void WriteAndPush(const void *data,uint64_t len)// 向Buffer写入并且造成_wirter偏移
    {
        Write(data,len);
        OffsetWriter(len);
    }

    void WriteString(const std::string &data)// 向Buffer写入string对象
    {
        Write(data.c_str(),data.size());
    }

    void WriteStringAndPush(const std::string &data)// 写入string对象并造成_writer偏移
    {
        WriteString(data);
        OffsetWriter(data.size());
    }

    void WriteBuffer(Buffer &data)// 写入Buffer对象
    {
        Write(data.ReadPosition(),data.ReadAbleSize());
    }

    void WriteBufferAndPush(Buffer &data)
    {
        WriteBuffer(data);
        OffsetWriter(data.ReadAbleSize());
    }

    /*完全可以这么写，但是我不这么干。原因很简单，记性不好，老是会出bug
    void Write(const void *data,uint64_t len,bool IsOffset = true)
    {
        //.....
        if(IsOffset) OffsetWriter(len);
    }*/

    void Read(void *buf,uint64_t len)
    {
        if(len > ReadAbleSize()) abort();// 只能读取有效的数据
        std::copy(ReadPosition(),ReadPosition() + len,(char *)buf);// 将[_reader,_reader+len]之间的数据拷贝到buf之后的位置
    }

    void ReadAndPop(void *buf,uint64_t len)// 读取数据并且移动_reader，即从Buffer当中删除数据
    {
        Read(buf,len);
        OffsetReader(len);
    }

    std::string ReadAsString(uint64_t len)// 读取len个数据，在该函数内部封装成string对象返回出去
    {
        if(len > ReadAbleSize()) abort();
        std::string str;
        str.resize(len);
        Read(&str[0],len);
        return std::move(str);// 减少拷贝
    }

    std::string ReadAsStringAndPop(uint64_t len)
    {
        if(len > ReadAbleSize()) abort();
        std::string str = ReadAsString(len);
        OffsetReader(len);
        return std::move(str);
    }

    std::basic_string<unsigned char> ReadAsUnsignedChar(uint64_t len)
    {
        if(len > ReadAbleSize()) abort();
        std::basic_string<unsigned char> str;
        str.resize(len);
        Read(&str[0],len);
        return std::move(str);
    }

    std::basic_string<unsigned char> ReadAsUnsignedCharAndPop(uint64_t len)
    {
        if(len > ReadAbleSize()) abort();
        std::basic_string<unsigned char> str = ReadAsUnsignedChar(len);
        OffsetReader(len);
        return std::move(str);
    }


    char *FindEndOfLine()// 寻找一行的结束标志'\n'
    {
        char *res = (char *)memchr(ReadPosition(),'\n',ReadAbleSize());
        return res;
    }

    std::string GetLine()// 获取一行数据
    {
        char *pos = FindEndOfLine();
        if(pos == nullptr) return "";
        return ReadAsString(pos - ReadPosition() + 1);// +1是为了将'\n'一并返回
    }

    std::string GetLineAndPop()
    {
        std::string str = GetLine();
        OffsetReader(str.size());
        return std::move(str);
    }

    void Clear()// 清空Buffer
    {
        _reader = 0;
        _writer = 0;
    }
private:
    std::vector<char> _buffer;// 使用vector进行空间管理
    /*两个指针*/
    uint64_t _reader;// 有效数据的起始位置
    uint64_t _writer;// 有效数据的结束位置
};
/*--------------------------------------------------------------------------------------------------------------------------*/

/*------------------------Socket模块---------------------------------
作用：将Socket库的接口封装起来，方便使用*/
#define MAX_LISTEN 1024// 全连接队列大小
class Socket
{
public:
    Socket(int sockfd = -1):_sockfd(sockfd) {}

    ~Socket() {}

    int GetFd() {return _sockfd;}// 获取套接字文件描述符

    bool Create()// 创建套接字
    {
        _sockfd = socket(AF_INET,SOCK_STREAM,0);// 只支持TCP协议
        if(_sockfd < 0)
        {
            ERROR_LOG("CREATE SOCKET ERROR: %s",strerror(errno));
            return false;
        }
        NonBlock();// 任何套接字都设置非阻塞
        return true;
    }

    bool Bind(const std::string &ip,uint16_t port)// 封装bind
    {
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port);
        local.sin_addr.s_addr = inet_addr(ip.c_str());
        socklen_t len = sizeof(local);
        
        int n = bind(_sockfd,(struct sockaddr *)&local,len);
        if(n < 0)
        {
            ERROR_LOG("BIND SOCKET ERROR: %s",strerror(errno));
            return false;
        }
        return true;
    }

    bool Listen(int backlog = MAX_LISTEN)// 封装listen，启动监听
    {
        int n = listen(_sockfd,backlog);
        if(n < 0)
        {
            ERROR_LOG("SOCKET LISTEN ERROR: %s",strerror(errno));
            return false;
        }
        return true;
    }

    bool Connect(const std::string &ip,uint16_t port)// 向某个服务器发起连接
    {
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port);
        local.sin_addr.s_addr = inet_addr(ip.c_str());
        socklen_t len = sizeof(local);

        int n = connect(_sockfd,(struct sockaddr *)&local,len);
        if(n < 0)
        {
            ERROR_LOG("CONNECT SERVER ERROR: %s",strerror(errno));
            return false;
        }
        return true;
    }

    int Accept()// 接收新连接上来
    {
        int connfd = accept(_sockfd,nullptr,nullptr);// 不关心客户端信息
        if(connfd < 0)
        {
            ERROR_LOG("SOCKET ACCEPT ERROR: %s",strerror(errno));
            return -1;
        }
        NonBlock();// 任何套接字都设置非阻塞
        return connfd;
    }

    ssize_t Recv(void *buf,size_t len,int flag = 0)// 默认为阻塞读取
    {
        ssize_t n = recv(_sockfd,buf,len,flag);
        if(n <= 0)
        {
            if(errno == EAGAIN || errno == EINTR) return 0;// 如果读取到了文件结束，或者是被系统打断，这是正常的，返回0
            ERROR_LOG("SOCKET RECV ERROR: %s",strerror(errno));
            return -1;
        }
        return n;
    }

    ssize_t NoBlockRecv(void *buf,size_t len)// 非阻塞式读取
    {
        return Recv(buf,len,MSG_DONTWAIT);
    }

    ssize_t Send(const void *buf,size_t len,int flag = 0)// 默认为阻塞式的发送数据
    {
        ssize_t n = send(_sockfd,buf,len,flag);
        if(n < 0)
        {
            if(errno == EAGAIN || errno == EINTR) return 0;
            ERROR_LOG("SOCKET SEND ERROR: %s",strerror(errno));
            return -1;
        }
        return n;
    }

    ssize_t NoBlockSend(void *buf,size_t len)
    {
        return Send(buf,len,MSG_DONTWAIT);
    }

    void Close()// 关闭套接字
    {
        if(_sockfd != -1)
        {
            close(_sockfd);
            _sockfd = -1;
        }
    }

    bool CreateServer(uint16_t port,const std::string &ip = "0.0.0.0")// 直接创建一个服务器套接字
    {
        if(Create() == false) return false;
        ReuseAddr();
        if(Bind(ip,port) == false) return false;
        if(Listen() == false) return false;
        return true;
    }

    bool CreateClinet(const std::string &ip,uint16_t port)// 直接创建一个客户端连接
    {
        if(Create() == false) return false;// 创建失败
        if(Connect(ip,port) == false) return false;// 连接失败
        return true;
    }

    void ReuseAddr()// 开启端口地址重用
    {
        int val = 1;
        setsockopt(_sockfd,SOL_SOCKET,SO_REUSEADDR,(void *)&val,sizeof(val));
        val = 1;
        setsockopt(_sockfd,SOL_SOCKET,SO_REUSEPORT,(void *)&val,sizeof(val));
    }

    void NonBlock()// 设置非阻塞
    {
        int flag = fcntl(_sockfd,F_GETFL,0);// 获取当前属性
        fcntl(_sockfd,F_SETFL,flag | O_NONBLOCK);
    }
private:
    int _sockfd;// 监听套接字
};
/*-------------------------------------------------------------------------------------------------*/

/*-----------------------------------------------------Channel模块----------------------------------------------------------
作用：将文件描述符和事件给一起封装起来，方便做一个处理，同时还设置了对应事件的回调函数，当某个文件描述符的某个事件触发时可以快速响应*/
class EventLoop;// 一个声明
class Channel
{
private:
    using EventCallbakc = std::function<void ()>;// 触发事件后的回调
public:
    Channel(EventLoop *loop,int fd)
        :_fd(fd),_loop(loop),_events(0),_revents(0)
    {}

    int GetFd() {return _fd;}

    uint32_t GetEvents() {return _events;}// 获取监控事件

    uint32_t GetRevents() {return _revents;}// 获取触发事件

    void SetRevents(uint32_t events) {_revents = events;}// 设置就绪事件

    void SetReadCallback(const EventCallbakc &cb) {_read_callback = cb;}// 设置读事件触发后的回调函数

    void SetWriteCallback(const EventCallbakc &cb) {_write_callback = cb;}

    void SetErrorCallback(const EventCallbakc &cb) {_error_callback = cb;}

    void SetCloseCallback(const EventCallbakc &cb) {_close_callback = cb;}

    void SetEventCallback(const EventCallbakc &cb) {_event_callback = cb;}

    bool ReadAble() {return (_events & EPOLLIN);}// 当前文件描述符是否监控了可读事件？

    bool WriteAble() {return (_events & EPOLLOUT);}// 当前文件描述符是否监控了可写事件？

    void EnableRead() {_events |= EPOLLIN;Update();}// 添加读事件监控,Updata()的作用是告诉其他模块要进行一个事件监控的更新

    void EnableWrite() {_events |= EPOLLOUT;Update();}// 添加写事件监控

    void EnableETMode() {_events |= EPOLLET;Update();}// 开启ET模式

    void DisableRead() {_events &= ~EPOLLIN;Update();}// 取消读事件监控

    void DisableWrite() {_events &= ~EPOLLOUT;Update();}// 取消写事件监控

    void DisableAll() {_events = 0;Update();}// 取消所有事件监控

    /*--------------这两个接口的功能不属于Channel模块，因为他们涉及到事件的ADD、MOD、DEL，Channel模块不具备这个功能------------------*/
    void Update();// 更新事件监控

    void Remove();// 移除监控，区别于DisableAll，Remove是不再对_fd进行监控
    /*--------------所以他们的实现被放在了类外，并且需要通过其他模块才能实现(EevntLoop)--------------------------------------------*/

    void HandleEvent()// 通过触发的事件判断调用哪个回调
    {
        if((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
        {
            if(_read_callback) _read_callback();
        }
        if(_revents & EPOLLOUT)
        {
            if(_write_callback) _write_callback();
        }
        else if(_revents & EPOLLERR)
        {
            if(_error_callback) _error_callback();
        }
        else if(_revents & EPOLLHUP)// 出现了严重的异常
        {
            if(_close_callback) _close_callback();
        }
        if(_event_callback) _event_callback();// 任意事件触发
    }
private:
    int _fd;// 文件描述符
    EventLoop *_loop;// Reactor
    uint32_t _events;// 需要监控的事件
    uint32_t _revents;// 触发的事件
    EventCallbakc _read_callback;// 可读事件触发后的回调函数
    EventCallbakc _write_callback;// 可写事件触发后的回调函数
    EventCallbakc _error_callback;// 错误事件触发后的回调函数
    EventCallbakc _close_callback;// 连接断开事件触发后的回调函数
    EventCallbakc _event_callback;// 任意事件触发后的回调函数
};
/*----------------------------------------------------------------------------------------------------------*/

/*-----------------------------------Poller模块-------------------------------------------------------
作用：进行事件的监控，对事件的监控实际上需要文件描述符和事件，而恰好这两个被Channel模块所封装起来了，说以Poller模块监控的是Channel对象*/
#define MAX_EPOLLEVENTS 1024
class Poller
{
private:    
    bool HanChannel(Channel *channle)// 判断Channel对象是否被Poller模块所管理
    {
        auto it = _channels.find(channle->GetFd());
        if(it == _channels.end())
        {
            return false;
        }
        return true;
    }

    void Update(Channel *channel,int op)// 更新epoll的监控事件
    {
        int fd = channel->GetFd();
        struct epoll_event ev;
        ev.data.fd = fd;
        ev.events = channel->GetEvents();

        int n = epoll_ctl(_epfd,op,fd,&ev);
        if(n < 0)
        {
            ERROR_LOG("EPOLLCTL ERROR: %s",strerror(errno));
        }
    }
public:
    Poller()
    {
        _epfd = epoll_create(MAX_EPOLLEVENTS);// 创建epoll例程
        if(_epfd < 0)
        {
            ERROR_LOG("EPOLL CREATE ERROR: %s",strerror(errno));
            abort();
        }
    }

    void UpdateEvent(Channel *channel)// 更新事件的监控
    {
        bool ret = HanChannel(channel);
        if(ret == false)// 如果当前Channel对象并不被Poller所管理，那么它就是一个新的Channel
        {
            _channels.insert(std::make_pair(channel->GetFd(),channel));// 让Poller模块管理起来
            Update(channel,EPOLL_CTL_ADD);
            return;
        }
        Update(channel,EPOLL_CTL_MOD);// 如果已经是存在的Channel对象
    }

    void RemoveEevnt(Channel *channel)// 移除事件对某个Channel的事件监控
    {
        auto it = _channels.find(channel->GetFd());
        if(it != _channels.end()) 
        {
            _channels.erase(it);
        }
        Update(channel,EPOLL_CTL_DEL);
    }

    void Poll(std::vector<Channel *> *active)// 开始监控，并且返回事件触发的Channel
    {
        int ret = epoll_wait(_epfd,_evs,MAX_EPOLLEVENTS,-1);
        if(ret < 0)
        {
            if(errno == EINTR) return;// 被系统打断则视为正常
            ERROR_LOG("EPOLL WAIT ERROR: %s",strerror(errno));
            abort();
        }
        for(int i=0;i<ret;i++)
        {
            auto it = _channels.find(_evs[i].data.fd);
            if(it == _channels.end()) abort();// 如果触发事件对应的Channel并不被Poller所管理，就说明有问题
            it->second->SetRevents(_evs[i].events);// 通知事件
            active->push_back(it->second);// 将触发事件的Channel交给外部(这个外部是EventLoop)
        }
    }
private:    
    int _epfd;// epoll例程,在内核当中打开一个事件表
    struct epoll_event _evs[MAX_EPOLLEVENTS];// 事件触发之后，epoll_wait会将触发的事件放到这个数组当中
    std::unordered_map<int,Channel *> _channels;// Poller模块会负责通知事件，通知的对象就是Channel对象
};
/*--------------------------------------------------------------------------------------------------------------------*/

/*---------------------------------TimerTask类-------------------------------------------
作用：封装一下定时任务，方便其他模块的管理*/
using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void ()>;
class TimerTask// 定时任务类
{
public:
    TimerTask(uint64_t id,uint32_t timeout,const TaskFunc &cb,int turns)
        :_id(id),_timeout(timeout),_task_cb(cb),_canceled(false)// 默认不取消定时任务
        ,_turns(turns)
    {}

    ~TimerTask()
    {
        if(_canceled == false) _task_cb();// 对象析构时执行定时任务
        _release();// 释放TimerWheel中所管理的TimerTask资源
    }

    void Cancel() {_canceled = true;}// 取消定时任务

    void SetRelease(const ReleaseFunc &cb) {_release = cb;}// 由管理器设置

    uint32_t DelayTime() {return _timeout;}// 返回定时时间

    void ReduceTurns() {--_turns;}// 减少圈数

    int GetTurns() {return _turns;}// 获得圈数

    void SetTurns(int turns) {_turns = turns;}
private:
    uint64_t _id;// 定时任务id，方便定位、查询、管理
    uint32_t _timeout;// 定时任务的超时时间，即多久之后执行任务
    bool _canceled;// 是否取消定时任务
    TaskFunc _task_cb;// 定时器任务
    ReleaseFunc _release;// 删除TimerWheel当中保存的TimerTask信息，防止内存泄漏
    int _turns;// 圈数
};
/*---------------------------------------------------------------------------------------------------------------*/

/*------------------------------------------------TimerWheel模块------------------------------------------------
作用：时间轮管理器，管理TimerTask对象，并进行时间滚动*/
class TimerWheel
{
private:
    using WeakTask = std::weak_ptr<TimerTask>;// 指向TimerTask的弱指针
    using PtrTask = std::shared_ptr<TimerTask>;// 指向TimerTask的引用计数型指针

    static int CreateTimerfd()
    {
        int timerfd = timerfd_create(CLOCK_MONOTONIC,0);// 创建定时器
        if(timerfd < 0)
        {
            ERROR_LOG("TIMERFD CREATE ERROR: %s",strerror(errno));
            abort();
        }
        struct itimerspec itime;
        itime.it_value.tv_sec = 1;
        itime.it_value.tv_nsec = 0;// 第一次超时时间为1s后
        itime.it_interval.tv_sec = 1;
        itime.it_interval.tv_nsec = 0;// 第一次超时时间过后，每隔1s超时一次
        timerfd_settime(timerfd,0,&itime,nullptr);
        return timerfd;
    }

    int ReadTimerfd()
    {
        uint64_t times;
        int n = read(_timerfd,&times,8);// 只能8个字节的读
        if(n < 0)
        {
            ERROR_LOG("READ TIMEFD FAILED: %s",strerror(errno));
            abort();
        }
        // 每次从_timerfd当中读取数据后，_timerfd内的内容会被清空，所以读事件不会重复被出发
        return times;// 返回值是超时次数
    }

    void RunTimerTask()
    {
        _tick = (_tick + 1) % _capacity;// 秒针转动一次
        for(auto it = _wheel[_tick].begin();it != _wheel[_tick].end();)
        {
            if((*it)->GetTurns() >= 1)// 圈数>=1的定时任务不应该被执行，而是减少圈数
            {
                (*it)->ReduceTurns();
                ++it;
            }
            else 
            {
                it = _wheel[_tick].erase(it);// 圈数=0的TimerTask的shared_ptr会被销毁，引用计数会递减
            }
        }
    }

    void OnTime()// 超时时间到，读事件触发，读事件触发后的回调函数
    {
        int times = ReadTimerfd();
        for(int i=0;i<times;i++)// 返回的是超时次数，超时几次就处理几次任务
        {
            RunTimerTask();
        }
    }

    void RemoveTimer(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it != _timers.end())
        {
            _timers.erase(it);
        }
    }

    /*--------------这三个函数在实现EventLoop之后会自然理解-------------------*/
    void TimerAddInLoop(uint64_t id,uint32_t delay,const TaskFunc &cb)
    {
        int turns = delay / _capacity;// 计算圈数
        PtrTask pt(new TimerTask(id,delay,cb,turns));// 创建TimerTask对象
        pt->SetRelease(std::bind(&TimerWheel::RemoveTimer,this,id));// 设置TimerTask析构时，取消TimerWheel对其的管理
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);// 在时间轮当中找到适当的位置
        _timers[id] = WeakTask(pt);// 存到哈希表当中去
    }

    void TimerRefreshInLoop(uint64_t id)// 真实的刷新定时器
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return;// 必须保证要刷新的定时器被TimerWheel所管理
        }
        PtrTask pt = it->second.lock();// 弱指针向shared_ptr转化
        int delay = pt->DelayTime();
        int turns = delay / _capacity;// 计算圈数
        pt->SetTurns(turns);// 设置圈数
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);// 重新添加新的定时任务对象,实际上没有拷贝对象，而是拷贝了shared_ptr，延长对象的生命周期
    }

    void TimerCancelInLoop(uint64_t id)// 取消定时器
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return;
        }
        PtrTask pt = it->second.lock();
        if(pt) pt->Cancel();// TimerTask当中提供了取消定时器的接口
    }
    /*-----------------------------------------------------------------------*/
public:
    TimerWheel(EventLoop *loop)
        :_capacity(60),_tick(0),_wheel(_capacity),_loop(loop),
        _timerfd(CreateTimerfd()),_timer_channel(new Channel(_loop,_timerfd))// 每一个文件描述符都会配备一个Channel对象
    {
        _timer_channel->SetReadCallback(std::bind(&TimerWheel::OnTime,this));
        _timer_channel->EnableRead();// 启动读事件监控
    }

    /*-------------------------这三个函数需要在EventLoop实现后才能实现---------------------------------*/
    void TimerAdd(uint64_t id,uint32_t timeout,const TaskFunc &cb);

    void TimerRefresh(uint64_t id);

    void TimerCancel(uint64_t id);
    /*-------------------------原因在实现EventLoop时做解释--------------------------------------------*/
    bool HasTimer(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return false;
        }
        return true;
    }
private:
    int _tick;// 秒针，心博，每秒钟变化一次
    int _capacity;// 表盘的最大数量，模拟钟表
    std::vector<std::list<PtrTask>> _wheel;// 时间轮，存放TimerTask的智能指针
    std::unordered_map<uint64_t,WeakTask> _timers;// 管理TimerTask对象
    EventLoop *_loop;// Reactor
    int _timerfd;// timerfd_create的返回值，OS提供给我们的定时器
    std::unique_ptr<Channel> _timer_channel;
};
/*--------------------------------------------------------------------------------------------------------------------*/

/*------------------------------------------------EventLoop模块-----------------------------------------------------------
作用：将Channel、Poller、TimerWheel模块进行一个整合，实际上就是实现一个Reactor，其中还做了保证线程安全的处理*/
class EventLoop
{
private:
    using Functor = std::function<void()>;
    void RunAllTask()// 执行任务队列当中的所有任务
    {
        std::vector<Functor> functor;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _tasks.swap(functor);// 交换之后，_tasks就为空了，其他线程就没有任务执行了
        }
        for(auto &f:functor)
        {
            f();// 执行任务
        }
    }

    static int CreateEventFd()
    {
        int efd = eventfd(0,EFD_CLOEXEC | EFD_NONBLOCK);
        if(efd < 0)
        {
            ERROR_LOG("CREATE EVENTFD ERROR: %s",strerror(errno));
            abort();
        }
        return efd;
    }

    void ReadEventfd()// 从_event_fd当中读取数据
    {
        uint64_t res = 0;
        int ret = read(_event_fd,&res,sizeof(res));// 数据读取出来之后,_event_fd的内容就会被清空
        if(ret < 0)
        {
            if(errno == EINTR || errno == EAGAIN)
            {
                return;
            }
            ERROR_LOG("READ EVENTFD ERROR: %s",strerror(errno));
            abort();
        }
    }

    void WeakUpEventFd()// 向_evenfd_fd写入数据，即触发_event_fd的可读事件
    {
        uint64_t val = 1;
        int ret = write(_event_fd,&val,sizeof(val));
        if(ret < 0)
        {
            if(errno == EINTR)
            {
                return;
            }
            ERROR_LOG("READ EVENTFD ERROR: %s",strerror(errno));
            abort();
        }
    }
public:
    EventLoop()
        :_thread_id(std::this_thread::get_id()),// 绑定线程
        _event_fd(CreateEventFd()),// 创建事件通知
        _event_channel(new Channel(this,_event_fd)),// 事件通知本身也是一个文件描述符和事件，所以需要封装成Channel
        _timer_wheel(this)
    {
        // _event_fd也需要被监听
        _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd,this));
        _event_channel->EnableRead();
    }

    void Start()// 启动Reactor
    {
        while(true)
        {
            std::vector<Channel *> actives;// 保存事件触发的Channel对象
            _poller.Poll(&actives);// 所有事件触发的Channel对象都会被放在actives中
            for(auto &channel:actives)
            {
                channel->HandleEvent();// 挨个处理事件触发之后的任务
            }
            RunAllTask();// 最后执行任务队列的所有任务
        }
    }

    bool IsInLoop()// 判断当前EventLoop对象是否处于构造线程中
    {
        return (_thread_id == std::this_thread::get_id());
    }

    void AssertInLoop()
    {
        if(_thread_id != std::this_thread::get_id()) abort();
    }

    void RunInLoop(const Functor &cb)// 所有任务的执行都必须经过这个接口
    {
        if(IsInLoop())
        {
            return cb();// 处于构造线程的任务直接执行
        }
        QueueInLoop(cb);// 否则压入任务队列
    }

    void QueueInLoop(const Functor &cb)
    {
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _tasks.push_back(cb);
        }
        WeakUpEventFd();// 任务队列有任务，向_event_fd写入数据，触发读事件，读事件触发后才会执行RunAllTask()继而执行任务队列的任务
    }

    void UpdateEvent(Channel *channel) {_poller.UpdateEvent(channel);}

    void RemoveEvent(Channel *channel) {_poller.RemoveEevnt(channel);}

    void TimerAdd(uint64_t id,uint32_t delay,const TaskFunc &cb) {_timer_wheel.TimerAdd(id,delay,cb);}

    void TimerRefresh(uint64_t id) {_timer_wheel.TimerRefresh(id);}

    void TimerCancel(uint64_t id) {_timer_wheel.TimerCancel(id);}

    bool HasTimer(uint64_t id) {_timer_wheel.HasTimer(id);}
private:    
    std::thread::id _thread_id;// 线程id,我们的目标是就是One Thread One Loop，所以每个Reactor都对应一个线程
    int _event_fd;// eventfd的返回值，一个事件通知
    std::unique_ptr<Channel> _event_channel;// Channel对象
    Poller _poller;
    std::vector<Functor> _tasks;// 任务队列,保证线程安全的核心
    std::mutex _mutex;// 保证任务队列的互斥访问
    TimerWheel _timer_wheel;// 定时器
};

/*---------------------------------Channel、TimerWheel当中的某些成员函数必须等EventLoop实现之后才能实现----------------------------------*/
void Channel::Remove() {_loop->RemoveEvent(this);}

void Channel::Update() {_loop->UpdateEvent(this);}

void TimerWheel::TimerAdd(uint64_t id,uint32_t delay,const TaskFunc &cb)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerAddInLoop,this,id,delay,cb));
}

void TimerWheel::TimerRefresh(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerRefreshInLoop,this,id));
}

void TimerWheel::TimerCancel(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerCancelInLoop,this,id));
}
/*---------------------------------------------------------------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------------------------------------*/

/*-----------------------------------LoopThread模块-----------------------------------------------------
功能：将EventLoop和线程一起封装起来，使其达到One Thread One Loop的效果*/
class LoopThread
{
private:    
    void ThreadEntry()// 新线程的入口函数，并且实例化出EventLoop
    {
        EventLoop loop;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _loop = &loop;
            _cond.notify_all();// 确实创建了一个EventLoop对象，GetLoop()才能返回
        }
        loop.Start();// 线程内启动loop，loop对象不会被销毁
    }
public:
    LoopThread()
        :_loop(nullptr),_thread(std::thread(&LoopThread::ThreadEntry,this))
    {}

    EventLoop *GetLoop()// 获取EventLoop对象的地址
    {
        EventLoop *loop = nullptr;
        {// 获取的时候就要保证EventLoop对象一定存在
            std::unique_lock<std::mutex> lock(_mutex);
            _cond.wait(lock,[&](){return _loop != nullptr;});// 如果_loop为空就一直阻塞
            loop = _loop;
        }
        return loop;
    }
private:    
    std::mutex _mutex;
    std::condition_variable _cond;
    EventLoop *_loop;// 这个对象需要在线程内实例化
    std::thread _thread;
};
/*---------------------------------------------------------------------------------------------*/

/*---------------------------------------------LoopThreadPool模块---------------------------------------------------
作用：实现一个线程池，对LoopThread进行管理和调度*/
class LoopThreadPool
{
public:
    LoopThreadPool(EventLoop *baseloop)
        :_thread_count(0),_next_index(0),_baseloop(baseloop)
    {}

    void SetThreadCount(int count) {_thread_count = count;}// 设置线程数量

    void Create()// 启动线程池
    {
        if(_thread_count > 0)
        {
            _threads.resize(_thread_count);
            _loops.resize(_thread_count);
            for(int i=0;i<_thread_count;i++)
            {
                _threads[i] = new LoopThread();// LoopThread一旦创建就开始工作
                _loops[i] = _threads[i]->GetLoop();
            }
        }
    }

    EventLoop *NextLoop()// 任务的分发要平均分配给每个线程，这里使用循环轮转的方式分配
    {
        // 这里的返回值都是返回给Connection对象的，目的就是让连接在对应的线程当中被处理
        // 返回EventLoop而不是返回线程的原因在于One Thread One Loop，返回EventLoop就是返回线程
        if(_thread_count == 0) return _baseloop;// 如果线程数量为0，就返回主线程的EventLoop
        _next_index = (_next_index + 1) % _thread_count;
        return _loops[_next_index];
    }
private:    
    int _thread_count;// 线程数量
    int _next_index;// 下标
    EventLoop *_baseloop;// 主线程EventLoop
    std::vector<LoopThread *> _threads;// 用数组管理LoopThread对象
    std::vector<EventLoop *> _loops;// 用数组管理记录EventLoop对象
};
/*-----------------------------------------------------------------------------------------------------------*/

/*----------------------------------------------Any模块------------------------------------------------------
作用：实现一个类，能够存储不同类型的对象，目的是方便存储协议和进行协议转换*/
class Any
{
public:
    Any()
        :_content(nullptr)
    {}

    template <class T>
    Any(const T &val)
        :_content(new placeholder<T>(val)) 
    {}

    Any(const Any &other)// 拷贝构造，深拷贝
        :_content(other._content ? other._content->clone() : nullptr)
    {} 

    ~Any() {delete _content;}

       
    void swap(Any &other) {std::swap(_content,other._content);}

    template <class T>
    T *get()// 获得存储的对象的指针
    {
        if(typeid(T) != _content->type()) abort();
        return &((placeholder<T> *)_content)->_val;
    }

    template <class T>
    Any &operator=(const T &val)
    {
        Any(val).swap(*this);
        return *this;
    }

    Any &operator=(const Any &other)
    {
        Any(other).swap(*this);
        return *this;
    }
private:
    class holder// 基类
    {
        public:
            virtual ~holder() {}
            virtual const std::type_info &type() = 0;// 纯虚函数，返回类型
            virtual holder *clone() = 0;// 克隆出一个对象
    };

    template <class T>
    class placeholder : public holder// 派生类-模板类
    {
        public:
            placeholder(const T &val)
                :_val(val)
            {}

            virtual const std::type_info &type() {return typeid(T);}// 虚函数重写
            
            virtual holder *clone() {return new placeholder(_val);}// 拷贝一个placeholder对象

            T _val;// 存储的对象
    };

    holder *_content;// 父类指针，构成多态
};
/*------------------------------------------------------------------------------------------------------------------*/

/*-----------------------------------------Connection模块-----------------------------------------------------------
作用：封装一个完整的连接，其中包括连接的套接字、事件、缓冲区、协议上下文、对应的处理动作等等*/
typedef enum {DISCONNECTED,CONNECTING,CONNECTED,DISCONNECTING}ConnStatu;// 定义连接的几种状态：未连接、连接种、已连接、正在断开连接
class Connection;
using PtrConnection = std::shared_ptr<Connection>;// Connection对象的智能指针，组件使用使用者操作Connection时只能通过只能指针操控
class Connection : public std::enable_shared_from_this<Connection>// 让this指针能够作为智能指针
{
private:    
    using ConnectedCallback = std::function<void(const PtrConnection &)>;// 连接建立成功后的回调函数
    using MessageCallback = std::function<void(const PtrConnection &,Buffer *)>;// 消息到来后的回调函数
    using ClosedCallback = std::function<void(const PtrConnection &)>;// 连接关闭之后的回调函数
    using AnyEventCallback = std::function<void(const PtrConnection &)>;// 连接的任意事件触发后的回调函数

    /*-----------------------下面这5个函数都是Channel的回调函数------------------------------*/
    void HandelRead()// 读事件触发
    {
        while(true)// ET模式，一次性读完数据
        {
            char buffer[1024];
            ssize_t ret = _socket.NoBlockRecv(buffer,sizeof(buffer) - 1);
            if(ret < 0)// 如果读取数据时发生错误
            {
                ShutdownInLoop();// 需要关闭连接，但并不是立马关闭连接，而是在管理连接之前做一些处理
                return;
            }
            if(ret == 0) break;
            _in_buffer.WriteAndPush(buffer,ret);// 将读到的数据写入缓冲区
        }
        if(_in_buffer.ReadAbleSize() > 0)// 调用回调
        {
            if(_message_callback) _message_callback(shared_from_this(),&_in_buffer);
        }
    }

    void HandleWrite()// 写事件触发
    {
        ssize_t ret = _socket.NoBlockSend(_out_buffer.ReadPosition(),_out_buffer.ReadAbleSize());
        if(ret < 0)// 如果发送出错
        {
            if(_in_buffer.ReadAbleSize() > 0)// 如果输入缓冲区还有数据
            {
                if(_message_callback) _message_callback(shared_from_this(),&_in_buffer);
            }
            Release();// 释放连接
            return;
        }
        _out_buffer.OffsetReader(ret);// 指针偏移，成功发送数据
        if(_out_buffer.ReadAbleSize() == 0)// 如果没有数据可以发送了
        {
            _channel.DisableWrite();// 取消写事件的监听
            if(_statu == DISCONNECTING)// 如果是正在断开的情况下，就需要释放连接
            {
                Release();
                return;
            }
        }
    }

    void HandleClose()// 连接断开事件触发
    {
        if(_in_buffer.ReadAbleSize() > 0)
        {
            if(_message_callback) _message_callback(shared_from_this(),&_in_buffer);
        }
        Release();
    }

    void HandleError()// 异常事件触发
    {
        HandleClose();// 不做处理，直接关闭连接
    }

    void HandleEvent()// 任意事件触发
    {
        if(_enable_inactive_release == true)// 如果启动了非活跃连接定时销毁 
            _loop->TimerRefresh(_conn_id);// 那么就要刷新定时器
        if(_event_callback) 
            _event_callback(shared_from_this());
    }
    /*-----------------------上面这5个函数都是Channel的回调函数------------------------------*/

    void EstablishedInLoop()// 连接建立成功之后，需要进行一些设置：改变状态、启动事件监听等等
    {
        if(_statu != CONNECTING) abort();
        _statu = CONNECTED;
        _channel.EnableRead();
        _channel.EnableETMode();// 启动ET模式
        if(_connected_callback) _connected_callback(shared_from_this());
    }

    void CancelInactiveReleaseInLoop()// 取消非活跃连接定时销毁
    {
        _enable_inactive_release = false;
        if(_loop->HasTimer(_conn_id))
        {
            _loop->TimerCancel(_conn_id);
        }
    }

    void ReleaseInLoop()// 实际的连接释放接口
    {
        _statu = DISCONNECTED;
        _channel.Remove();// 取消事件监听
        _socket.Close();// 关闭连接
        if(_loop->HasTimer(_conn_id)) CancelInactiveReleaseInLoop();
        if(_closed_callback) _closed_callback(shared_from_this());
        if(_server_closed_callback) _server_closed_callback(shared_from_this());
    }

    void SendInLoop(std::shared_ptr<Buffer> buf)// 发送数据
    {
        if(_statu == DISCONNECTED) return;// 连接关闭状态，不予发送数据
        _out_buffer.WriteBufferAndPush(*buf);
        if(_channel.WriteAble() == false)// 如果Channel并没有开启写事件监听
        {
            _channel.EnableWrite();
        }
    }

    void ShutdownInLoop()// 暂缓关闭连接，通常是正常关闭连接时，关闭之前需要做一些处理
    {
        _statu = DISCONNECTING;
        if(_in_buffer.ReadAbleSize() > 0)// 如果输入缓冲区还有数据
        {
            if(_message_callback) _message_callback(shared_from_this(),&_in_buffer);
        }
        if(_out_buffer.ReadAbleSize() > 0)// 如果输出缓冲区还有数据
        {
            if(_channel.WriteAble() == false)
            {
                _channel.EnableWrite();
            }
        }
        if(_out_buffer.ReadAbleSize() == 0)// 数据全部发送完毕了，则关闭连接
        {
            Release();
        }
    }

    void EnableInactiveReleaseInLoop(int sec)// 启动非活跃连接定时销毁
    {
        _enable_inactive_release = true;
        if(_loop->HasTimer(_conn_id))// 如果已经存在了，就只是刷新一下定时器
        {
            return _loop->TimerRefresh(_conn_id);
        }
        _loop->TimerAdd(_conn_id,sec,std::bind(&Connection::Release,this));// 添加定时器，并设置定时销毁任务
    }

    void DisableInactiveReleaseInLoop()// 取消非活跃连接定时销毁
    {
        _enable_inactive_release = false;
        if(_loop->HasTimer(_conn_id))
        {
            return _loop->TimerCancel(_conn_id);
        }
    }

    /*切换协议上下文*/
    void UpgradeInLoop(const Any &context,
                       const ConnectedCallback &conn,
                       const MessageCallback &msg,
                       const ClosedCallback &closed,
                       const AnyEventCallback &event)
    {
        _context = context;
        _connected_callback = conn;
        _message_callback = msg;
        _closed_callback = closed;
        _event_callback = event;
    }
public:
    Connection(EventLoop *loop,uint64_t conn_id,int sockfd)
        :_conn_id(conn_id),_sockfd(sockfd),_enable_inactive_release(false),
        _loop(loop),_statu(CONNECTING),_socket(_sockfd),_channel(loop,_sockfd)
    {
        _channel.SetCloseCallback(std::bind(&Connection::HandleClose,this));
        _channel.SetEventCallback(std::bind(&Connection::HandleEvent,this));
        _channel.SetReadCallback(std::bind(&Connection::HandelRead,this));
        _channel.SetWriteCallback(std::bind(&Connection::HandleWrite,this));
        _channel.SetErrorCallback(std::bind(&Connection::HandleError,this));
    }

    int GetFd() {return _sockfd;}

    int GetId() {return _conn_id;}

    bool Connected() {return _statu == CONNECTED;}// 判断当前连接是否处于已连接状态

    void SetContext(const Any &context) {_context = context;}// 设置协议上下文

    Any *GetContext() {return &_context;}

    void SetConnectedCallback(const ConnectedCallback &cb) {_connected_callback = cb;}

    void SetMessgageCallback(const MessageCallback &cb) {_message_callback = cb;}

    void SetClosedCallback(const ClosedCallback &cb) {_closed_callback = cb;}

    void SetAnyEventCallback(const AnyEventCallback &cb) {_event_callback = cb;}

    void SetServerClosedCallback(const ClosedCallback &cb) {_server_closed_callback = cb;}

    void Established()// 连接建立之初要进行一些初始化设置
    {
        _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop,this));
    }

    void Send(const char *data,size_t len)
    {
        std::shared_ptr<Buffer> buf(new Buffer());
        buf->WriteAndPush(data,len);
        _loop->RunInLoop(std::bind(&Connection::SendInLoop,this,buf));// 用bind绑定不知道为什么会报错，索性用lambda表达式
    }

    void Shutdown()// 连接正常断开时，释放连接之前要处理一些工作
    {
        _loop->RunInLoop(std::bind(&Connection::ShutdownInLoop,this));
    }

    void Release()
    {
        // 任何情况下直接释放连接的操作都应该是最低优先级，即无论什么情况下都应该放在最后执行，即放入任务队列
        // 比方说，abcd四个连接，所有连接都设置了30s非活跃定时销毁，如果a的业务处理了40s，恰好b又是定时器任务
        // 那么处理b事件的时候必定会释放后续的所有连接(因为都超时了嘛)，但是c和d不知道自己被释放了，继续处理任务，就会导致服务器崩溃
        // 所以不能这么干，必须让b放到最后执行
        _loop->QueueInLoop(std::bind(&Connection::ReleaseInLoop,this));
    }

    void EnableInactiveRelease(int sec)// 启动非活跃连接的定时销毁
    {
        _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop,this,sec));
    }

    void DisableInactiveRelease()// 取消非活跃连接的定时销毁
    {
        _loop->RunInLoop(std::bind(&Connection::DisableInactiveReleaseInLoop,this));
    }

    void Upgrade(const Any &context,// Upgrade:协议升级(切换)，本质就是切换一下Any类当中存储的内容
                       const ConnectedCallback &conn,
                       const MessageCallback &msg,
                       const ClosedCallback &closed,
                       const AnyEventCallback &event)
    {
        _loop->AssertInLoop();// 切换的任务必须在构造线程立即执行，否则后续的处理可能还是以前的协议
        _loop->RunInLoop(std::bind(&Connection::UpgradeInLoop,this,context,conn,msg,closed,event));
    }
private:
    uint64_t _conn_id;// 标识符，还可以用来作为定时器的id
    int _sockfd;// 连接的套接字
    bool _enable_inactive_release;// 是否启动非活跃连接定时断开
    EventLoop *_loop;// 连接所关联的EventLoop，关联了EventLoop就说明关联了某个线程
    ConnStatu _statu;// 当前连接的状态
    Socket _socket;// 套接字的管理
    Channel _channel;// 套接字的事件管理
    Buffer _in_buffer;// 输入缓冲区，存放从TCP读取到数据
    Buffer _out_buffer;// 输出缓冲区，存放要发送给对端的数据
    Any _context;// 协议上下文

    ConnectedCallback _connected_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    AnyEventCallback _event_callback;

    /*Connection模块还需要被其他模块所管理，该回调函数的功能与TimerTask的Release类似*/
    ClosedCallback _server_closed_callback;
};
/*---------------------------------------------------------------------------------------------------------------*/

/*------------------------------------Acceptor模块------------------------------------------------
作用：封装监听套接字*/
class Acceptor
{
private:
    using AcceptCallback = std::function<void(int)>;

    int CreateServer(int port)// 监听套接字
    {
        bool ret = _socket.CreateServer(port);
        if(ret == false)
        {
            ERROR_LOG("ACCEPTOR CREATE SERVER ERROR");
            abort();
        }
        return _socket.GetFd();
    }

    void HandleRead()// 读事件触发后的回调
    {
        int connfd = _socket.Accept();
        if(connfd < 0) return;
        if(_accept_callback) _accept_callback(connfd);
    }
public:
    Acceptor(EventLoop *loop,int port)
        :_socket(CreateServer(port)),_loop(loop),_channel(loop,_socket.GetFd())
    {
        _channel.SetReadCallback(std::bind(&Acceptor::HandleRead,this));
        // 构造函数当中不能直接启动读事件监听，因为此时回调函数还没有设置
        // 如果立即有事件触发，就不会调用回调函数，则这个连接得不到处理，从而造成资源泄露
    }

    void SetAcceptCallback(const AcceptCallback &cb) {_accept_callback = cb;}

    void Listen() {_channel.EnableRead();}// 启动监听
private:
    Socket _socket;// 用于创建监听套接字
    EventLoop *_loop;// 主Reactor
    Channel _channel;
    AcceptCallback _accept_callback;
};
/*-------------------------------------------------------------------------------------------------------------------*/

/*-------------------------------------------------TcpServer模块----------------------------------------------------
作用：所有模块的一个整合，也是Reactor的一部分，核心工作就是接收新连接，然后将新连接分配调度给其他从Reactor*/
class TcpServer
{
private:    
    using ConnectedCallback = std::function<void(const PtrConnection &)>;// 连接建立成功后的回调函数
    using MessageCallback = std::function<void(const PtrConnection &,Buffer *)>;// 消息到来后的回调函数
    using ClosedCallback = std::function<void(const PtrConnection &)>;// 连接关闭之后的回调函数
    using AnyEventCallback = std::function<void(const PtrConnection &)>;// 连接的任意事件触发后的回调函数
    using Functor = std::function<void()>;
    void NewConnection(int fd)// 监听套接字可读事件触发后的回调函数，功能就是封装出一个Connection
    {
        _next_id++;
        PtrConnection conn(new Connection(_pool.NextLoop(),_next_id,fd));// 分配EventLoop，绑定对应的线程
        conn->SetMessgageCallback(_message_callback);
        conn->SetClosedCallback(_closed_callback);
        conn->SetConnectedCallback(_connected_callback);
        conn->SetAnyEventCallback(_event_callback);
        conn->SetServerClosedCallback(std::bind(&TcpServer::RemoveConnection,this,std::placeholders::_1));

        if(_enable_inactive_release == true) conn->EnableInactiveRelease(_timeout);// 如果启动了非活跃连接定时销毁

        conn->Established();
        _conns.insert(std::make_pair(_next_id,conn));
    }

    void RemoveConnectionInLoop(const PtrConnection &conn)// 删除对某个Connection的管理
    {
        int id = conn->GetId();
        auto it = _conns.find(id);
        if(it != _conns.end())
        {
            _conns.erase(it);
        }
    }

    void RemoveConnection(const PtrConnection &conn)
    {
        _baseloop.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop,this,conn));
    }

    void RunAfterInLoop(const Functor &task,int delay)
    {   
        _next_id++;
        _baseloop.TimerAdd(_next_id,delay,task);
    }
public:
    TcpServer(int port)
        :_port(port),_next_id(0),_enable_inactive_release(false),
        _acceptor(&_baseloop,port),_pool(&_baseloop)
    {
        _acceptor.SetAcceptCallback(std::bind(&TcpServer::NewConnection,this,std::placeholders::_1));
        _acceptor.Listen();// 启动监听
    }

    void SetThreadCount(int count) {_pool.SetThreadCount(count);}// 设置线程数量

    void SetConnectedCallback(const ConnectedCallback &cb) {_connected_callback = cb;}

    void SetMessgageCallback(const MessageCallback &cb) {_message_callback = cb;}

    void SetClosedCallback(const ClosedCallback &cb) {_closed_callback = cb;}

    void SetAnyEventCallback(const AnyEventCallback &cb) {_event_callback = cb;}

    void EnableInactiveRelease(int timeout)// 启动非活跃连接定时删除
    {
        _timeout = timeout;
        _enable_inactive_release = true;
    }

    void RunAfter(const Functor &task,int delay)// 添加定时时间
    {
        _baseloop.RunInLoop(std::bind(&TcpServer::RunAfterInLoop,this,task,delay));
    }

    void Start()
    {
        _pool.Create();// 启动线程池
        _baseloop.Start();// 主线程EventLoop启动，服务器正式启动
    }
private:    
    uint64_t _next_id;// 自动增长的连接id
    int _port;// 端口号
    int _timeout;// 定义多久没有事件触发就是非活跃连接
    bool _enable_inactive_release;// 是否启动非活跃连接定时销毁
    EventLoop _baseloop;// 主线程的EventLoop
    Acceptor _acceptor;// 监听套接字
    LoopThreadPool _pool;// 线程池,其中就包含了从Reactor
    std::unordered_map<uint64_t,PtrConnection> _conns;// 保存、管理所有的Connection

    ConnectedCallback _connected_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    AnyEventCallback _event_callback;
};
/*--------------------------------------------------------------------------------------------------*/

class NetWork
{
public:
    NetWork()
    {
        DEBUG_LOG("SIGPIPE INIT!");
        signal(SIGPIPE,SIG_IGN);// 忽略管道异常,向已经关闭了的文件描述符写入数据的时候，不让进程退出
    }
};
static NetWork nw;// 包含"Server.hpp"头文件时，该对象自动创建，创建之后就设置了对SIGPIPE信号的忽略